/*
 * G2ODataInfo.cpp
 *
 *  Created on: Sep 11, 2016
 *      Author: ubuntu
 */

#include "G2ODataInfo.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../common.h"
#include "../Conf.h"
#include <sys/stat.h>
#include <sys/types.h>

#include <sys/socket.h>
#include <unistd.h>
#include <linux/un.h>
#include <netinet/in.h>
#include <netdb.h>

using namespace std;

G2ODataInfo::G2ODataInfo() : DataInfo()
{
	memset(&msg, 0, sizeof(msg));
	msg.curtime = time(NULL);
	m_buf = NULL;
	m_len = 0;
}

G2ODataInfo::~G2ODataInfo()
{
	if (m_buf)
		free(m_buf);
	G2O_free_msg(&msg);
}

bool G2ODataInfo::parse(unsigned char *buf, size_t len, int add_head, int add_tail)
{
	m_buf = buf;
	m_len = len;
	m_head = add_head;
	m_tail = add_tail;
	unsigned char *pBuf = buf + add_head;
	G2OParsePackage(pBuf, len, &msg);
	if (msg.is_valid == 0) {
		m_buf = NULL;
		return false;
	}
	return true;
}

void G2ODataInfo::debugInfo()
{
	switch (msg.id) {
	case G2O_LOGIN:
		{
			if (msg.login) {
				struct g2o_login *login = msg.login;
				debug(LOG_DEBUG, "登录请求:\n"
					"开发代码: %s, 设备ID: %s\n"
					"设备密钥: %s\n"
					"IMEI: %s, SIM: %s\n"
					"设备版本: %s", 
					login->dp_code, login->obdid,
					login->dev_key, login->dev_imei, login->dev_sim,
					login->dev_version
					);
			} else {
				debug(LOG_DEBUG, "解析不到位");
			}
		}
		break;
	case G2O_CONFIG_INFO:
		{
			debug(LOG_DEBUG, "配置信息");
		}
		break;
	case G2O_WARN_MSG:
		{
			if (!msg.warn) {
				debug(LOG_DEBUG, "报警消息有点儿邪乎啊");
				break;
			}
			struct g2o_warn *warn = msg.warn;
			switch (warn->id) {
			case G2O_WARN_TYPE_TIRED:
				debug(LOG_DEBUG, "连接驾驶报警: %s", warn->warn_msg ? warn->warn_msg : "无效数据"); 
				break;
			case G2O_WARN_TYPE_IDLE:
				debug(LOG_DEBUG, "怠速报警: %s", warn->warn_msg ? warn->warn_msg : "无效数据"); 
				break;
			case G2O_WARN_TYPE_FAST:
				debug(LOG_DEBUG, "急加速报警: %s", dateftime(msg.ts, "%F %H:%M:%S").c_str()); 
				break;
			case G2O_WARN_TYPE_DESC:
				debug(LOG_DEBUG, "急减速报警: %s", dateftime(msg.ts, "%F %H:%M:%S").c_str());
				break;
			case G2O_WARN_TYPE_VIBRATION:
				debug(LOG_DEBUG, "驻车震动报警: %s", dateftime(msg.ts, "%F %H:%M:%S").c_str());
				break;
			case G2O_WARN_TYPE_STARTUP:
				debug(LOG_DEBUG, "车辆启动报警: %s", warn->warn_msg ? warn->warn_msg : "无效数据"); 
				break;
			case G2O_WARN_TYPE_SHARP_TURN:
				debug(LOG_DEBUG, "急转弯报警: %s", warn->warn_msg ? warn->warn_msg : "无效数据"); 
				break;
			case G2O_WARN_TYPE_INSERT_PULLED:
				debug(LOG_DEBUG, "插入拔出报警: %s", dateftime(msg.ts, "%F %H:%M:%S").c_str()); 
				break;
			default:
				debug(LOG_DEBUG, "未知报警类型: %04X : %s", warn->id, warn->warn_msg ? warn->warn_msg : "无效数据"); 
				break;
			}
		}
		break;
	case G2O_TRAVEL_STCS:
		{
			if (msg.travel == NULL) {
				debug(LOG_DEBUG, "不正常的行程统计");
				break;
			}
			struct g2o_travel *travel = msg.travel;
			switch (travel->type) {
			case G2O_TRAVEL_TYPE_START:
				debug(LOG_DEBUG, "行程开始: %d, %s", travel->number, dateftime(travel->ts, "%F %H:%M:%S").c_str());
				break;
			case G2O_TRAVEL_TYPE_FINISH:
				debug(LOG_DEBUG, "行程结束: %d, %s\n"
						"开始GPS: %lf, %lf; 结束GPS: %lf, %lf\n"
						"怠数次数: %d, 怠速时间: %d, 里程: %.2f, 油耗: %.2f"
						, travel->number, dateftime(travel->ts, "%F %H:%M:%S").c_str(),
						travel->lng_start, travel->lat_start, travel->lng_end, travel->lat_end, 
					 travel->idling_cnt, travel->idling_tm, travel->mileage * 0.01, travel->oil * 0.01);
				break;
			case G2O_TRAVEL_TYPE_GPS_START:
				debug(LOG_DEBUG, "GPS行程开始: %d, %s", travel->number, dateftime(travel->ts, "%F %H:%M:%S").c_str());
				break;
			case G2O_TRAVEL_TYPE_GPS_FINISH:
				debug(LOG_DEBUG, "GPS行程结束: %d, %s", travel->number, dateftime(travel->ts, "%F %H:%M:%S").c_str());
				break;
			default:
				debug(LOG_DEBUG, "未知行程统计消息类型");
				break;
			}
		}
		break;
	case G2O_PACKED_DATA:
		{
			struct g2o_gps *gps = msg.gps;
			for (; gps; gps = gps->next) {
				debug(LOG_DEBUG, "GPS数据: \n"
						"时间: %s\n"
						"定位模式: %d, 方向: %d, 速度: %d, 高度: %d\n"
						"经度: %lf, 纬度: %lf",
						dateftime(gps->ts, "%F %H:%M:%S").c_str(),
						gps->position_mode, gps->direction,
						gps->speed, gps->height,
						gps->longitude, gps->latitude
					 );
			}
			struct g2o_data_stream *stream = msg.stream;
			for (; stream; stream = stream->next) {
				int i = 0;
				char tmp[1024];
				int n = 0;
				while (stream->mark[i] != -1) {
					if (stream->mark[i] == 42) {
						n += snprintf(tmp, sizeof(tmp), "用油量: %d ml\n", stream->oil * 10);
					} else if (stream->mark[i] == 43) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "水温: %d 度\n", stream->water_temp);
					} else if (stream->mark[i] == 44) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "发动机进气温度: %d\n", stream->air_temp);
					} else if (stream->mark[i] == 46) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "电池当前电压: %.1f V\n", stream->voltage * 0.1);
					} else if (stream->mark[i] == 51) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "车速: %d Km/h\n", stream->car_speed);
					} else if (stream->mark[i] == 52) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "转速: %d rpm\n", stream->engine_speed);
					} else if (stream->mark[i] == 54) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "瞬时油耗: %.2f L/100Km\n", stream->instant_fuel_km * 0.01);
					} else if (stream->mark[i] == 55) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "瞬时油耗: %.2f L/h\n", stream->instant_fuel_h * 0.01);
					} else if (stream->mark[i] == 57) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "空气流量: %.2f g/s\n", stream->air_flow * 0.01);
					} else if (stream->mark[i] == 58) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "进气歧管绝对压力: %d\n", stream->press);
					} else if (stream->mark[i] == 64) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "滤波后剩余油量: %d %%\n", stream->remain_fuel);
					} else if (stream->mark[i] == 65) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "累计里程: %.1f Km\n", stream->mileage * 0.1);
					} else if (stream->mark[i] == 66) {
						n += snprintf(tmp+n, sizeof(tmp)-n, "里程ID: %d\n", stream->mileage_id);
					}
					i++;
				}
				n += snprintf(tmp+n, sizeof(tmp)-n, "体检时间: %s", dateftime(stream->ts, "%F %H:%M:%S").c_str());
				debug(LOG_DEBUG, "数据流: %s", tmp);
			}
		}
		break;
	case G2O_UPGRADE:
		{
			if (msg.upgrade == NULL)
				break;
			struct g2o_upgrade *upgrade = msg.upgrade;
			switch (upgrade->type) {
			case 0x01:
				debug(LOG_DEBUG, "请求最新版本: %s", upgrade->version);
				break;
			case 0x02:
				debug(LOG_DEBUG, "请求升级包数据: %s", upgrade->version);
				break;
			default:
				debug(LOG_DEBUG, "无有此类型升级: %d", upgrade->type);
				break;
			}
		}
		break;
	case G2O_BEAT_DATA:
		{
			debug(LOG_DEBUG, "心跳数据\n"
					"GSM 信号强度: %d", msg.gsm_sig_inensity);
		}
		break;
	case G2O_UNKNOWN_000A:
		debug(LOG_DEBUG, "非内部服务: %04X", msg.id);
		break;
	case G2O_UNKNOWN_000F:
		debug(LOG_DEBUG, "非内部服务: %04X", msg.id);
		break;
	default:
		debug(LOG_DEBUG, "未知类型: %04X", msg.id);
		break;
	}
}

int G2ODataInfo::sendBuf(unsigned char *buf, size_t len, const char *key)
{
	int k = 0;
	switch (msg.id) {
	case G2O_LOGIN:
		k = send_login_rsp(buf, len, key);
		return k;
	case G2O_CONFIG_INFO:
		k = send_config_rsp(buf, len);
		break;
	case G2O_WARN_MSG:
		k = send_warn_rsp(buf, len);
		break;
	case G2O_TRAVEL_STCS:
		k = send_travel_rsp(buf, len);
		break;
	case G2O_PACKED_DATA:
		k = send_packed_data_rsp(buf, len);
		break;
	case G2O_UPGRADE:
		k = send_upgrade_rsp(buf, len);
		break;
	case G2O_BEAT_DATA:
		k = send_beat_rsp(buf, len);
		break;
	case G2O_UNKNOWN_000A:
		return 0;
	case G2O_UNKNOWN_000F:
		k = send_unknown_000f(buf, len);
		break;
	default:
		return 0;
	}
	if (k <= 0)
		return 0;
	int res = 0;
	unsigned short crc = rsp_crc16(buf, k, len, key, &res);
	if (res < 0)
		return 0;
	buf[k++] = (crc >> 8) & 0xFF;
	buf[k++] = crc & 0xFF;
	buf[0] = k & 0xFF;
	buf[1] = (k >> 8) & 0xFF;
	return k;
}

int G2ODataInfo::send_login_rsp(unsigned char *buf, size_t len, const char *key)
{
	unsigned short dlen = 0;
	int pos = 2;
	int req_res, beat_cyc, gpssam_cyc, gpstrs_cyc, datasam_cyc, datatrs_cyc, data_rsp;
	req_res = 1;
	beat_cyc = 1;
	gpssam_cyc = 1;
	gpstrs_cyc = 4;
	datasam_cyc = 15;
	datatrs_cyc = 30;
	data_rsp = 1;
	Connection *pConn = getConf()->cpool->grab();
	if (pConn) {
		try {
			Query query = pConn->query();
			query << "select req_res, beat_cyc, gpssam_cyc, gpstrs_cyc, datasam_cyc, datatrs_cyc, data_rsp from zb_g2o_allobd where obdid='" << m_obdid << "'";
			StoreQueryResult res = query.store();
			if (res.num_rows() > 0) {
				req_res = atoi(res[0][0].c_str());
				beat_cyc = atoi(res[0][1].c_str());
				gpssam_cyc = atoi(res[0][2].c_str());
				gpstrs_cyc = atoi(res[0][3].c_str());
				datasam_cyc = atoi(res[0][4].c_str());
				datatrs_cyc = atoi(res[0][5].c_str());
				data_rsp = atoi(res[0][6].c_str());
			}
		} catch (mysqlpp::BadQuery &er) {
			if (er.errnum() != 1146) {
				debug(LOG_DEBUG, "Query error: %s", er.what());
			}
		}
		getConf()->cpool->release(pConn);
	}
	buf[pos++] = G2O_LOGIN_RSP & 0xFF;
	buf[pos++] = (G2O_LOGIN_RSP >> 8) & 0xFF;
	buf[pos++] = msg.pro;
	buf[pos++] = req_res; /* 0 登录失败 1登录成功 2服务器超负荷重引导服务器地址， 3 服务器指向错误重指向服务器地址*/
	buf[pos++] = beat_cyc; /* 心跳周期*/
	buf[pos++] = gpssam_cyc; /* GPS采样周期 */
	buf[pos++] = gpstrs_cyc; /* GPS传输周期 */
	buf[pos++] = datasam_cyc; /* 数据流采样周期 */
	buf[pos++] = datatrs_cyc; /* 传输周期 */
	buf[pos++] = data_rsp; /* 是否应答 0 不应答， 1应答*/

	memcpy(&buf[pos], key, 32);
	pos += 32;

	dlen = pos - 2;
	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;
	time_t ts = time(NULL);
	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8) & 0xFF;
	buf[pos++] = (ts >> 16) & 0xFF;
	buf[pos++] = (ts >> 24) & 0xFF;
	for (int i = 0; i < 32; i++) {
		buf[pos++] = '0';
	}
	unsigned short crc = crc16(0xFFFF, buf, pos);
	pos -= 32;
	buf[pos++] = (crc >> 8)& 0xFF;
	buf[pos++] = crc & 0xFF;

	buf[0] = pos & 0xFF;
	buf[1] = (pos >> 8) & 0xFF;

	return pos;
}

int G2ODataInfo::send_config_rsp(unsigned char *buf, size_t len)
{
	int pos = 2;
	int dlen = 0;
	time_t ts = time(NULL);
	buf[pos++] = G2O_CONFIG_RSP & 0xFF;
	buf[pos++] = (G2O_CONFIG_INFO >> 8 ) & 0xFF;
	buf[pos++] = msg.pro;					// 协议号

	buf[pos++] = 0x02;

	dlen = pos - 2;
	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8) & 0xFF;
	buf[pos++] = (ts >> 16) & 0xFF;
	buf[pos++] = (ts >> 24) & 0xFF;

	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;

	return pos;
}

int G2ODataInfo::send_warn_rsp(unsigned char *buf, size_t len)
{
	int pos = 2;
	int dlen = 0;
	time_t ts = time(NULL);
	buf[pos++] = G2O_WARN_MSG_RSP & 0xFF;
	buf[pos++] = (G2O_WARN_MSG_RSP >> 8) & 0xFF;
	buf[pos++] = msg.pro;

	dlen = pos - 2;
	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;
	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8) & 0xFF;
	buf[pos++] = (ts >> 16) & 0xFF;
	buf[pos++] = (ts >> 24) & 0xFF;

	return pos;
}

int G2ODataInfo::send_travel_rsp(unsigned char *buf, size_t len)
{
	int pos = 2;
	int dlen = 0;
	time_t ts = time(NULL);

	buf[pos++] = G2O_TRAVEL_RSP & 0xFF;
	buf[pos++] = (G2O_TRAVEL_RSP >> 8)& 0xFF;
	buf[pos++] = msg.pro;

	buf[pos++] = msg.travel->type;
	buf[pos++] = msg.travel->number & 0xFF;
	buf[pos++] = (msg.travel->number >> 8) & 0xFF;

	buf[pos++] = 1;

	dlen = pos - 2;
	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;

	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8) & 0xFF;
	buf[pos++] = (ts >> 16) & 0xFF;
	buf[pos++] = (ts >> 24) & 0xFF;

	return pos;
}

int G2ODataInfo::send_packed_data_rsp(unsigned char *buf, size_t len)
{
	int pos = 2;
	int dlen = 0;
	time_t ts = time(NULL);

	buf[pos++] = G2O_PACKED_DATA_RSP & 0xFF;
	buf[pos++] = (G2O_PACKED_DATA_RSP >> 8)& 0xFF;
	buf[pos++] = msg.pro;

	dlen = pos - 2;
	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;
	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8)& 0xFF;
	buf[pos++] = (ts >> 16)& 0xFF;
	buf[pos++] = (ts >> 24)& 0xFF;

	return pos;
}

int G2ODataInfo::send_beat_rsp(unsigned char *buf, size_t len)
{
	int pos = 2;
	int dlen = 0;
	time_t ts = time(NULL);
	buf[pos++] = G2O_BEAT_RSP & 0xFF;
	buf[pos++] = (G2O_BEAT_RSP >> 8) & 0xFF;
	buf[pos++] = msg.pro;

	dlen = pos - 2;
	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;
	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8) & 0xFF;
	buf[pos++] = (ts >> 16) & 0xFF;
	buf[pos++] = (ts >> 24) & 0xFF;

	return pos;
}

int G2ODataInfo::send_unknown_000f(unsigned char *buf, size_t len)
{
	int pos = 2;
	int dlen = 0;
	time_t ts = time(NULL);
	buf[pos++] = G2O_UNKNOWN_000F_RSP & 0xFF;
	buf[pos++] = (G2O_UNKNOWN_000F_RSP >> 8) & 0xFF;
	buf[pos++] = msg.pro;

	dlen = pos - 2;
	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;
	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8)& 0xFF;
	buf[pos++] = (ts >> 16)& 0xFF;
	buf[pos++] = (ts >> 24)& 0xFF;

	return pos;
}

int G2ODataInfo::send_upgrade_rsp(unsigned char *buf, size_t len)
{
	int pos = 2;
	int dlen = 0;
	time_t ts = time(NULL);
	struct g2o_upgrade *upgrade = msg.upgrade;
	buf[pos++] = G2O_UPGRADE_RSP & 0xFF;
	buf[pos++] = (G2O_UPGRADE_RSP >> 8) & 0xFF;
	buf[pos++] = msg.pro;

	buf[pos++] = upgrade->type;

	switch (upgrade->type) {
	case 0x01:
		{
			int maxv = 0;
			int minv = 0;
			int version = 0;
			sscanf(msg.upgrade->version, "V%02d.%02d", &maxv, &minv);
			version = get_g2o_version();
			if ((maxv * 100 + minv) < version) {
				minv = version % 100;
				maxv = version / 100;
				struct stat statbuf;
				unsigned char md[20];
				int block = 0;
				if (md5(get_g2o_file(), md) < 0)
					goto notupgrade;
				if (stat(get_g2o_file(), &statbuf) < 0)
					goto notupgrade;
				block = statbuf.st_size / 512;
				buf[pos++] = 6;
				sprintf((char *)(buf+pos), "V%02d.%02d", maxv, minv);
				pos += 6;
				buf[pos++] = block & 0xFF;
				buf[pos++] = (block >> 8) & 0xFF;
				buf[pos++] = (block >> 16) & 0xFF;
				buf[pos++] = (block >> 24) & 0xFF;
				for (int i = 0; i < 16; i++)
					sprintf((char *)(buf+pos+i*2), "%02X", md[i]);
				pos += 32;
				break;
			} 
notupgrade:
			buf[pos++] = msg.upgrade->vsn_len;
			memcpy(buf+pos, msg.upgrade->version, msg.upgrade->vsn_len);
			pos += msg.upgrade->vsn_len;
		}
		break;
	case 0x02:
		{
			int up_pos = atoi(upgrade->version);
			int up_len = 512;
			int file_pos = (up_pos - 1) * 512;
			int nread = 0;
			buf[pos++] = up_len & 0xFF;				/* 数据长度: 2*/
			buf[pos++] = (up_len >> 8) & 0xFF;

			buf[pos++] = up_pos & 0xFF;				/* 数据包包号: 4*/
			buf[pos++] = (up_pos >> 8) & 0xFF;
			buf[pos++] = (up_pos >> 16) & 0xFF;
			buf[pos++] = (up_pos >> 24) & 0xFF;

			FILE *fp = fopen(get_g2o_file(), "r");
			if (!fp)
				return -1;
			fseek(fp, file_pos, SEEK_SET);
			nread = fread(buf+pos, 1, up_len, fp);
			if (nread < 0)
				return -1;

			pos += nread;

			fclose(fp);
		}
		break;
	}

	dlen = pos - 2;
	buf[pos++] = ts & 0xFF;
	buf[pos++] = (ts >> 8) & 0xFF;
	buf[pos++] = (ts >> 16) & 0xFF;
	buf[pos++] = (ts >> 24) & 0xFF;
	buf[0] = dlen & 0xFF;
	buf[1] = (dlen >> 8) & 0xFF;

	return pos;
}

bool G2ODataInfo::set_obdid(char *obdid, size_t len)
{
	switch (msg.id) {
	case G2O_LOGIN:
		if (msg.login) {
			strncpy(obdid, msg.login->obdid, len);
			strncpy(m_obdid, msg.login->obdid, sizeof(m_obdid));
			break;
		} else {
			return false;
		}
		break;
	default:
		strncpy(m_obdid, obdid, len);
		break;
	}

	return true;
}

void G2ODataInfo::writelog(const char *path)
{
	int fd = socket(AF_UNIX, SOCK_STREAM, 0);
	struct sockaddr_un addr;
	int mhlen = 0;
	if (fd < 0)
		goto send_fail;

	bzero(&addr, sizeof(addr));
	addr.sun_family = AF_UNIX;
	strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);

	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		close(fd);
		goto send_fail;
	}

	mhlen = DM_TAG_HEAD_LEN + 17;
	if (m_head >= mhlen) {
		int n = 0;
		unsigned char *pBuf = m_buf + m_head - mhlen;
		memcpy(pBuf, DM_TAG_HEAD, DM_TAG_HEAD_LEN);
		n += DM_TAG_HEAD_LEN;
		pBuf[n++] = SV_G2O;
		pBuf[n++] = (msg.curtime >> 24) & 0xFF;
		pBuf[n++] = (msg.curtime >> 16) & 0xFF;
		pBuf[n++] = (msg.curtime >> 8) & 0xFF;
		pBuf[n++] = msg.curtime & 0xFF;
		memcpy(pBuf+n, m_obdid, 12);
		if (write(fd, pBuf, m_len + mhlen) < 0) {
			close(fd);
			goto send_fail;
		}
	} else {
		debug(LOG_DEBUG, "不能出现这种情况");
		close(fd);
		goto send_fail;
	}

	close(fd);
	return;

send_fail:
	locallog();
	free(m_buf);
	m_buf = NULL;
}

void G2ODataInfo::locallog()
{
	char file[40];
	unsigned char *pBuf = m_buf + m_head;
	struct custime cus = timetocstm(msg.curtime);
	snprintf(file, sizeof(file), "log/g2o%04d%02d%02d%02d%02d", cus.year, cus.month, cus.day, cus.hour, cus.min);
	FILE *fp = fopen(file, "a+");
	if (!fp)
		return;

	fprintf(fp, "%08X", msg.curtime);
	for (int i = 0; i < 12; i++)
		fprintf(fp, "%02X", m_obdid[i]);
	for (size_t i = 0; i < m_len; i++) {
		fprintf(fp, "%02X", pBuf[i]);
	}
	fprintf(fp, "\n");
	fclose(fp);
}

unsigned short G2ODataInfo::get_type()
{
	return msg.id;
}

unsigned short G2ODataInfo::rsp_crc16(unsigned char *buf, size_t len, size_t blen, const char *key, int *res)
{
	unsigned char *p, *tmp = NULL;
	unsigned short crc;
	int init_size = 32;
	if (blen > len && blen - len >= init_size) {
		p = buf;
	} else {
		tmp = (unsigned char *)malloc(len+init_size);
		if (tmp) {
			memcpy(tmp, buf, len);
			p = tmp;
		} else {
			*res = -1;
			return 0;
		}
	}
	memcpy(p+len, key, init_size);
	crc = crc16(0xFFFF, p, len + init_size);
	if (tmp)
		free(tmp);
	*res = 1;
	return crc;
}
